package com.zyl.callable;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @author zhaoyl
 * @date 2024/5/15 22:35
 * @description 说明
 * Callable创建多线程:可以有返回值，并抛出异常
 */
public class callableTest {
    public static void main(String[] args)  {
      // new Thread(new MyThread()).start();//Thread 启动多线程

        //   new Thread(  new Runnable(f).start();
       // new Thread(  new Thread(futureTask<V>).start();
      //   new Thread(  new Thread(futureTask<V>(Callable)).start();

        //启动
        MyCallableThread thread = new MyCallableThread();
        FutureTask futureTask = new FutureTask(thread);//适配类
        new Thread(futureTask,"线程A").start();
        new Thread(futureTask,"线程B").start();//运行结果会被缓存，效率高
        /*
        再分析一下结果，可以看到明明启动了a，b两个线程，但是只输出了一个线程的结果，这是因为运行的结果会被缓存
        "Callable结果 缓存" 可能指的是将Callable任务的结果存储在某种缓存中，以便后续的请求可以重用这个结果，
        而不是重新执行Callable任务。这种方式可以提高性能，特别是当Callable任务的执行代价较高时。
        * */
        //接收返回值
        try {
            //此处应该使用异步通信处理
            String  s = (String)futureTask.get();//注意：get()方法会产生阻塞
            System.out.println("接收返回值=="+s);
            String  s2 = (String)futureTask.get();//第二次冲缓存中取
            System.out.println("接收返回值2=="+s2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

}

class  MyCallableThread implements Callable<String>{

    @Override
    public String call() throws Exception {
        System.out.println("启动线程"+Thread.currentThread().getName()+"---Callable<String> 返回String类型");
        return "hello-Callable";
    }
}

//实现Runnable接口；（集成Thread类）
class MyThread implements Runnable{

    @Override
    public void run() {
        System.out.println("多线程Runnable接口");
    }
}
/*
* Runnable和Callable的区别主要包括以下几点：

方法不同：Runnable接口中定义的是run()方法，而Callable接口中定义的是call()方法。
返回值不同：Runnable的run()方法不返回任何值，但Callable的call()方法可以返回一个值，且返回值的类型可以通过泛型进行指定。
异常处理不同：Runnable的run()方法不能抛出checked Exception，而Callable的call()方法可以抛出一个checked Exception，并由其执行者进行捕获并处理。
启动方式不同：Runnable可以作为Thread构造器的参数，通过开启新的线程来执行，也可以通过线程池来执行。而Callable只能通过ExecutorService（线程池）执行。
使用场景不同：Runnable适用于那些不需要返回值，且不会抛出checked Exception的情况，如简单的打印输出或修改共享变量。Callable适用于需要返回值或抛出checked Exception的情况，如计算任务的结果处理或网络、IO操作等。
Future对象：运行Callable任务可以拿到一个Future对象，表示异步计算的结果，而Runnable没有这个功能
* */